package compilers.types;

import java.io.BufferedWriter;
import java.io.IOException;

import compilers.table.MemScope;

public class FloatType extends Type {

	public FloatType(float value, boolean constant) {
		super(constant, value);
	}
	
	public FloatType(boolean constant) {
		super(constant, 0);
	}

	public boolean isNumeric() {
		return true;
	}
	
	public void print(int tab) {
		for (int i=1;i<=tab;i++){System.out.print("\t");}System.out.print("|-");

		if (this.getfIdentifier() != null) {
			if (this.isArray()) {
				System.out.println("FloatType Array [" + this.getArray() +"] (" + getfIdentifier().getfIdentifier() + ")");
			} else {
				System.out.println("FloatType (" + getfIdentifier().getfIdentifier() + ")");
			}
		} else {
			if (this.isArray()) {
				System.out.println("FloatType Array [" + this.getArray() +"] (" + fValue + ")");
			} else {
				System.out.println("FloatType (" + fValue + ")");
			}
		}
	}

	public Type computeOperation(Type second, String op) {
		FloatType sec = (FloatType)second;
		if (second instanceof CharType) {
			CharType t = (CharType)second;
			sec = new FloatType(t.fValue, t.isConstant);
		} else if (second instanceof IntType) {
			IntType t = (IntType)second;
			sec = new FloatType(t.fValue, t.isConstant);
		}
		if (op.compareTo("+") == 0) {
			return new FloatType(fValue + sec.fValue, true);
		} else if (op.compareTo("*") == 0) {
			return new FloatType(fValue * sec.fValue, true);
		} else if (op.compareTo("-") == 0) {
			return new FloatType(fValue - sec.fValue, true);
		} else if (op.compareTo("/") == 0) {
			return new FloatType(fValue / sec.fValue, true);
		} else if (op.compareTo("<") == 0) {
			return new IntType((fValue < sec.fValue) ? 1 : 0, true);
		} else if (op.compareTo(">") == 0) {
			return new IntType((fValue > sec.fValue) ? 1 : 0, true);
		} else if (op.compareTo("<=") == 0) {
			return new IntType((fValue <= sec.fValue) ? 1 : 0, true);
		} else if (op.compareTo(">=") == 0) {
			return new IntType((fValue >= sec.fValue) ? 1 : 0, true);
		} else if (op.compareTo("==") == 0) {
			return new IntType((sec.fValue == fValue) ? 1 : 0, true);
		} else if (op.compareTo("!=") == 0) {
			return new IntType((sec.fValue != fValue) ? 1 : 0, true);
		} else if (op.compareTo("&&") == 0) {
			boolean b1 = (fValue != 0);
			boolean b2 = (sec.fValue != 0);
			return new IntType((b1 && b2) ? 1 : 0, true);
		} else if (op.compareTo("||") == 0) {
			boolean b1 = (fValue != 0);
			boolean b2 = (sec.fValue != 0);
			return new IntType((b1 || b2) ? 1 : 0, true);
		} else if (op.compareTo("%") == 0) {
			return new IntType(fValue % sec.fValue, true);
		}
		// Useless operation
		return null;
	}

	public Type computeFactor(String pre) {
		if (pre.compareTo("-") == 0) {
			return new FloatType(-fValue, true);
		} else if (pre.compareTo("!") == 0) {
			boolean b = (fValue != 0);
			return new FloatType((!b) ? 1 : 0, true);
		}
		return null;
	}

	public Type newInit() {
		return new FloatType(true);
	}
	
	public void generate(BufferedWriter writer, MemScope scope) throws IOException {		
		if (this.getfRes() == null) {
			System.out.println("throwing away useless code");
		} else {			
			if (this.getfIdentifier() == null) {
				writer.write("ldc r " + fValue + "\n");
			} else if (scope.get(getfIdentifier().getfIdentifier()) == -1) {
				// Array
				writer.write("ldc r 0\n");
			} else {
				writer.write("lod r " + scope.getDepth(getfIdentifier().getfIdentifier(), 0) + " " + scope.get(getfIdentifier().getfIdentifier()) + "\n");		
			}
			
			if(getCast() != null && !getCast().getClass().equals(this.getClass())) {
				writer.write("conv r " +  getCast().getPType() + "\n");
				if (!getCast().getClass().equals(getfRes().getClass())) {
					writer.write("conv " + getCast().getPType() + " r\n");
				}
			} else if (!this.getfRes().getClass().equals(this.getClass())) {
				writer.write("conv r " + this.getfRes().getPType() + "\n");
			}
		}
		
	}

	public char getPType() {
		return 'r';
	}
}
